package cn.itcast.web.utils;

import cn.itcast.domain.system.SysLog;
import cn.itcast.domain.system.User;
import cn.itcast.service.system.SysLogService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.UUID;

/*

    切面 = 通知+ 切入点表达式
 */
@Aspect // 表示该类是一个切面类
@Component
public class LogAspect {

  @Autowired
  private HttpServletRequest request;

  @Autowired
  private HttpSession session;

  @Autowired
  private SysLogService sysLogService;
  //切入点表达式： 返回值类型  包名.类名.方法名(形参类型)
  /*  @Pointcut("execution(* cn.itcast.web.controller.*.*.*(..))")
    public void pt(){}
*/

  //编写通知方法
  // 切入点表达式是可以使用逻辑运算符。 && || ！
  @Around("execution(* cn.itcast.web.controller.*.*.*(..)) && !execution(* cn.itcast.web.controller.system.SysLogController.*(..))")
  public Object saveLog(ProceedingJoinPoint pj) throws Throwable {
    // 如果是环绕通知，那么形参必须有一个ProceedingJoinPoint参数，ProceedingJoinPoint代表当前的目标方法
    //1.先让目标方法执行
    Object result = null;
    try {
      result = pj.proceed();
      //2. 创建SysLog对象
      SysLog sysLog = new SysLog();
      //3. 设置参数给SysLog对象
      sysLog.setId(UUID.randomUUID().toString());
      //获取当前的登陆者
      User loginUser = (User) session.getAttribute("loginUser");
      //设置用户名
      sysLog.setUserName(loginUser.getUserName());
      //设置登陆的ip
      sysLog.setIp(request.getRemoteAddr());
      //设置时间
      sysLog.setTime(new Date());
      //设置当前执行的目标方法名
      //getSignature()获取目标方法的签名
      String methodName = pj.getSignature().getName();
      sysLog.setMethod(methodName);
      //设置方法所属的类名
      String className = pj.getTarget().getClass().getName();
      sysLog.setAction(className);
      //设置公司
      sysLog.setCompanyId(loginUser.getCompanyId());
      sysLog.setCompanyName(loginUser.getCompanyName());
      //4. 保存到数据库中
      sysLogService.save(sysLog);
      return result;
    } catch (Throwable throwable) {
      throwable.printStackTrace();
      throw throwable;
    }
  }
}
